%{
    #include <stdint.h>
    #include <stdio.h>
    extern FILE *yyin;
    int yylex(void);
    void yyerror(char *);
    int32_t symboles[26];

    int nb_line;
%}
%token END_LINE IDENT AFFECT OPER1 OPER2 START END SEPAR ELEM
%token UNION INTER DIFF
%start list
%%
list : list instruction END_LINE        { nb_line++; }
     |
     ;
instruction : IDENT AFFECT expression   { symboles[$1] = $3; }
            | IDENT                     {
            printf("%c  { ", $1+'A');
            int i;
            for(i = 0; i < 32; i++) {
                if(symboles[$1] & (1 << i)) {
                    printf("%d ", i+1);
                }
            }
            printf("}\n");
}
            ;
expression : operande                   { $$ = $1; }
           | operande OPER2 operande    {
            switch($2) {
                case UNION:
                    $$ = $1 | $3;
                    break;
                case INTER:
                    $$ = $1 & $3;
                    break;
                case DIFF:
                    $$ = $1 ^ $3;
                    break;
            }
}
           | OPER1 operande             { $$ = ~ $2; }
           ;
operande : IDENT                        { $$ = symboles[$1]; }
         | ensemble                     { $$ = $1; }
         ;
ensemble : START END                    { $$ = 0; }
         | START list_elem END          { $$ = $2; }
         ;
list_elem : ELEM                        { $$ = 1 << ($1-1); }
          | ELEM SEPAR list_elem        { $$ = (1 << ($1-1)) | $3; }
          ;
%%
void yyerror(char *s) {
    fprintf(stderr, "%s: line %d\n", s, nb_line);
}

int main(int argc, char **argv) {
    nb_line = 1;

    if(argc > 2) {
        fprintf(stderr, "%s: too many arguments\nUsage: %s [FILE] or try %s --help.\n", argv[0], argv[0]);
        return 1;
    }
    if(argc == 2) {
        if(!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
            printf("Usage: %s [FILE]\n", argv[0]);
            return 0;
        }
        else {
            yyin = fopen(argv[1], "r");
            if(yyin == NULL) {
                fprintf(stderr, "%s: file not found\n", argv[0]);
                return 2;
            }
        }
    }

    yyparse();
    return 0;
}
